﻿/* 
* Copyright (c) 2010, The University of Texas at Austin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, 
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, 
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, 
* this list of conditions and the following disclaimer in the documentation and/or other materials 
* provided with the distribution.
*
* Neither the name of The University of Texas at Austin nor the names of its contributors may be 
* used to endorse or promote products derived from this software without specific prior written 
* permission.
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Bio.Data.Interfaces;
using Bio.Views.Structure.Editor.Internal.Data;

namespace Bio.Views.Structure.Editor.Internal.Algorithms
{
    public class ExportDiagramToCT
    {
        public static void ExportDiagram(StructureModelData diagram, string targetFile)
        {
            if (diagram == null ||
                diagram.Entity == null ||
                diagram.Entity.Sequence == null ||
                diagram.Entity.BasePairs == null)
                throw new ArgumentException("Structure model incomplete or empty");

            string headerFileLine = string.Format("Filename: {0}", Path.GetFileName(targetFile));
            string headerOrganismLine = (string.IsNullOrEmpty(diagram.ScientificName)) ? "Organism:" : string.Format("Organism: {0}", diagram.ScientificName);
            string headerAccessionLine = "Accession Number:";
            string headerCitationLine = "Citation and related information available at http://www.rna.ccbb.utexas.edu, Generated by CATUI";
            string seqLengthLine = string.Format("{0}   dG =     0.00  [initially     0.0]", diagram.Entity.Sequence.SequenceData.Count);

            StringWriter output = new StringWriter();
            output.WriteLine(headerFileLine);
            output.WriteLine(headerOrganismLine);
            output.WriteLine(headerAccessionLine);
            output.WriteLine(headerCitationLine);
            output.WriteLine(seqLengthLine);

            Dictionary<int, IBasePairBioEntity> mappedBP = new Dictionary<int, IBasePairBioEntity>();
            for (int i = 0; i < diagram.Entity.Sequence.SequenceData.Count; i++)
                mappedBP.Add(i, null);

            foreach (var bp in diagram.Entity.BasePairs)
            {
                mappedBP[bp.FivePrimeIndex] = bp;
                mappedBP[bp.ThreePrimeIndex] = bp;
            }

            int seqLength = diagram.Entity.Sequence.SequenceData.Count;
            foreach (var ntIdx in mappedBP.Keys)
            {
                if (mappedBP[ntIdx] != null)
                {
                    if (ntIdx == mappedBP[ntIdx].FivePrimeIndex)
                    {
                        output.WriteLine(string.Format("{0}  {1}  {2}  {3}  {4}  {0}", FormatRightJustify(seqLength, ntIdx + 1), diagram.Entity.Sequence.SequenceData[ntIdx].Value, FormatRightJustify(seqLength, ntIdx), FormatRightJustify(seqLength, ntIdx + 2), FormatRightJustify(seqLength, mappedBP[ntIdx].ThreePrimeIndex + 1)));
                    }
                    else
                    {
                        output.WriteLine(string.Format("{0}  {1}  {2}  {3}  {4}  {0}", FormatRightJustify(seqLength, ntIdx + 1), diagram.Entity.Sequence.SequenceData[ntIdx].Value, FormatRightJustify(seqLength, ntIdx), FormatRightJustify(seqLength, ntIdx + 2), FormatRightJustify(seqLength, mappedBP[ntIdx].FivePrimeIndex + 1)));
                    }
                }
                else
                {
                    output.WriteLine(string.Format("{0}  {1}  {2}  {3}  {4}  {0}", FormatRightJustify(seqLength, ntIdx + 1), diagram.Entity.Sequence.SequenceData[ntIdx].Value, FormatRightJustify(seqLength, ntIdx), FormatRightJustify(seqLength, ntIdx + 2), FormatRightJustify(seqLength, 0)));
                }
            }

            output.Flush();
            File.WriteAllText(targetFile, output.ToString());
        }

        private static string FormatRightJustify(int sequenceLength, int value)
        {
            int places = (sequenceLength % 10) + 1;
            String retValue = value.ToString();
            if (retValue.Length >= places) return retValue;
            else
            {
                StringBuilder formatString = new StringBuilder(retValue);
                for (int i = 0; i < (places - retValue.Length); i++) formatString.Insert(0, ' ');
                return formatString.ToString();
            }
        }
    }
}
